package fr.utbm.gi.vi51.project.formations;

import java.util.ArrayList;
import java.util.Collection;

import javax.vecmath.Point2d;

import fr.utbm.gi.vi51.project.environment.WorldModel;

public abstract class FormationBody {

	// protected BinarySearchTree<FormationSlot> slots;
	protected ArrayList<FormationSlot> slots;
	protected FormationOrientation orientation;
	private Point2d globalPosition = new Point2d();
	private float globalOrientation = 0;
	/**
	 * SubFormation bodies list.
	 */
	protected ArrayList<FormationBody> subFormations;
	/**
	 * Space between a formation and the center. Do note that this space is multiplied by 2 for the real space between
	 * two formations.
	 */
	protected static int SPACE_BETWEEN_FORMATIONS;

	public FormationBody() {
		this.slots = new ArrayList<>();
	}

	public Point2d getGlobalPosition() {
		return this.globalPosition;
	}

	public void setGlobalPosition(Point2d globalPosition) {
		this.globalPosition = globalPosition;
		if (this.subFormations != null && !this.subFormations.isEmpty()) {
			switch (this.subFormations.size()) {
			case 2:
				this.subFormations.get(0).setGlobalPosition(new Point2d(globalPosition.getX(), globalPosition.getY()));

				// Vector2d direction =
				// GeometryUtil.toOrientationVector(this.subFormations.get(0).getGlobalOrientation());
				// direction.normalize();
				// direction.scale(SPACE_BETWEEN_FORMATIONS);
				//
				// Point2d otherFormation = new Point2d(direction.getX(), direction.getY());

				this.subFormations.get(1).setGlobalPosition(
						new Point2d(globalPosition.getX(), globalPosition.getY() + SPACE_BETWEEN_FORMATIONS));
				break;
			case 3:
				this.subFormations.get(0).setGlobalPosition(new Point2d(globalPosition.getX(), globalPosition.getY()));
				this.subFormations.get(1).setGlobalPosition(
						new Point2d(globalPosition.getX(), globalPosition.getY() + SPACE_BETWEEN_FORMATIONS));
				this.subFormations.get(2).setGlobalPosition(
						new Point2d(globalPosition.getX() - SPACE_BETWEEN_FORMATIONS, globalPosition.getY()
								+ SPACE_BETWEEN_FORMATIONS / 2));
				break;
			case 4:
				break;
			default:
				break;
			}
		}
	}

	public float getGlobalOrientation() {
		return this.globalOrientation;
	}

	public void setGlobalOrientation(float globalOrientation) {
		// if (this.subFormations != null && !this.subFormations.isEmpty()) {
		// switch (this.subFormations.size()) {
		// case 2:
		// this.subFormations.get(0).setGlobalOrientation(globalOrientation + (float) Math.PI / 2);
		// this.subFormations.get(1).setGlobalOrientation(globalOrientation - (float) Math.PI / 2);
		// break;
		// case 3:
		// break;
		// case 4:
		// break;
		// default:
		// break;
		// }
		// } else {
		this.globalOrientation = globalOrientation;
		// }
	}

	public ArrayList<FormationSlot> getSlots() {
		return this.slots;
	}

	public FormationSlot getSlotAt(int index) {
		return (this.slots.get(index));
	}

	public void scale(int numberOfSlots) {
		SPACE_BETWEEN_FORMATIONS = WorldModel.getMarines().size() + 250;
		if (numberOfSlots > 0) {
			// Clear slots and set center
			this.slots.clear();
			for (int i = 0; i < WorldModel.getMarines().size(); i++) {
				WorldModel.getMarines().get(i).setFormationPosition(i);
			}
			// Add formations
			for (FormationSlot formationSlot : scaleAt(numberOfSlots, new Point2d())) {
				this.slots.add(formationSlot);
			}
		}
	}

	public abstract Collection<FormationSlot> scaleAt(int numberOfSlots, Point2d Position);

}
